#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <cassert>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <fcntl.h>

#include "log.hpp"

#define PATH_NAME "."
#define PROG_ID 0x66
#define SIZE 4096

#define FIFO_NAME "./fifo.ipc"

std::string TransToHex(key_t k)
{
    char ret[32] = {0};
    snprintf(ret, 32, "0x%x", k);
    return std::string(ret);
}

class Init
{
public:
    Init()   //构造函数，创建管道文件
    {
        int n = mkfifo(FIFO_NAME, 0666);
        // assert(n != -1);
        // (void*)n;   // 防止在release模式下因assert失效而报警告
        if(n == -1)
        {
            perror("Init mkfifo");
            exit(1);
        }
    }

    ~Init()   //析构函数
    {
        unlink(FIFO_NAME);
    }
};

#define READ O_RDONLY 
#define WRITE O_WRONLY

// 打开管道文件函数
// path为管道文件名， mode为打开方式
int OpenFifo(const std::string& pathname, int mode)
{
    int fd = open(FIFO_NAME, mode);
    if(fd == -1)
    {
        perror("fifo open");
        exit(2);
    }
    log("管道打开成功", NOTICE) << '\n';
    return fd;
}

// 等待读取函数
void WaitRead(int fd)
{
    log("等待中", NOTICE) << '\n';
    uint32_t temp = 0;
    ssize_t sz = read(fd, &temp, sizeof(uint32_t));   // 阻塞等待从管道中读取内容
    assert(sz == sizeof(uint32_t));
    (void*)sz;
}

// 唤醒读取函数
void WakeUp(int fd)
{
    uint32_t temp = 1;
    ssize_t sz = write(fd, &temp, sizeof(uint32_t));
    assert(sz == sizeof(uint32_t));
    (void*)sz;
    log("唤醒中", NOTICE) << '\n';
}

// 关闭管道文件函数
void CloseFifo(int fd)
{
    close(fd);
}